// from http://mindhacks.cn/2012/08/27/modern-cpp-practices/
#ifndef _TRASHWAR_SCOPE_GUARD_H_
#define _TRASHWAR_SCOPE_GUARD_H_

#include <functional>

class ScopeGuard {
public:
  ScopeGuard(std::function<void ()> on_exit_scope) : on_exit_scope_(on_exit_scope), dismissed_(false) { }
  
  ScopeGuard(const ScopeGuard&) = delete;
  const ScopeGuard& operator=(const ScopeGuard&) = delete;
  
  ~ScopeGuard() {
    if (!dismissed_) {
      on_exit_scope_();
    }
  }
  
  void Dismiss() {
    dismissed_ = true;
  }
  
private:
  std::function<void ()> on_exit_scope_;
  bool dismissed_;
};

#define SCOPEGUARD_LINENAME_CAT(name, line) name##line
#define SCOPEGUARD_LINENMAE(name, line) SCOPEGUARD_LINENAME_CAT(name, line)

#define ON_SCOPE_EXIT(callback) ScopeGuard SCOPEGUARD_LINENMAE(exit, __LINE__)(callback)

#endif
